/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.wider.foundation.channel;

import com.wider.foundation.Named;
import com.wider.foundation.Numbering;
import com.wider.foundation.concurrency.AdaptiveAgedExecutorPool;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.HashSet;
import java.util.concurrent.TimeUnit;

/**
 * This class acts as a container-factory which assembling and holding HttpChannel(s).
 * By using this class, user no need to manage its own Executor Pool, and all the child
 * HttpChannel(s) will share the Pool internally.
 *
 * @author William Choi <avextk@gmail.com>
 */
public class HttpChannels implements Named {
    public static final int DEFAULT_MAX_POOLSIZE = 16;
    
    private AdaptiveAgedExecutorPool    thrdpool;
    private HashSet<HttpChannel>        channels;
    private String      instname;
    private Numbering   sequence;

    public HttpChannels(String given){
        instname    = given;
        thrdpool    = null;
        channels    = new HashSet<HttpChannel>();
        sequence    = new Numbering(1, Integer.MAX_VALUE);
    }

    public void init(int max_pendings){
        init(max_pendings, DEFAULT_MAX_POOLSIZE);
    }

    public void init(int max_pendings, int max_poolsize){
        if (isReady())
            throw new IllegalStateException("Re-init is NOT supported.");

        thrdpool    = new AdaptiveAgedExecutorPool(getName() + "-ExecutorPool");
        thrdpool.init(max_pendings, max_poolsize);
    }

    public HttpChannel openChannel(String url) throws MalformedURLException, IOException{
        HttpChannel channel = new HttpChannel(getName() + "-Channel-" + sequence.next());
        channel.init(thrdpool);
        channel.connect(url);
        channels.add(channel);
        return channel;
    }

    public void closeChannel(HttpChannel channel, long timeout, TimeUnit unit) throws InterruptedException{
        channels.remove(channel);
        channel.disconnect(timeout, unit);
    }

    public void close(long timeout, TimeUnit unit) {
        thrdpool.shutdown();
        thrdpool.awaitTermination(timeout, unit);
        thrdpool = null;
    }
    
    public boolean isReady(){
        return (null != thrdpool);
    }

    public int getChannelCount(){
        return channels.size();
    }

    public int getPendingRequestCount(){
        return thrdpool.getPendingCount();
    }

    public int getActiveRequestCount(){
        return thrdpool.getActiveCount();
    }

    @Override
    public String getName() {
        return instname;
    }
}
